﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure;
using System.Net;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;

namespace AzureDriverExplorer_Client
{
    /// <summary>
    /// Interaction logic for VHDUpload.xaml
    /// </summary>
    public partial class VHDUpload : Page
    {
        bool Selected = false;
        bool Cancel = false;
        System.Threading.Thread thread;
        private Const cons = new Const();
        private System.Resources.ResourceManager ResManager;


        public VHDUpload()
        {
            InitializeComponent();
            AddConnectionLanguage();
            try
            {
                if (!File.Exists(Const.FileConfig))
                { File.Create(Const.FileConfig); }
                else
                {
                    try
                    {
                        // Create an instance of StreamReader to read from a file.
                        // The using statement also closes the StreamReader.
                        using (StreamReader sr = new StreamReader(Const.FileConfig))
                        {
                            String line;
                            // Read and display lines from the file until the end of 
                            // the file is reached.
                            List<VHDDataConfig> ListConfig = new List<VHDDataConfig>();
                            while ((line = sr.ReadLine()) != null)
                            {
                                try
                                {
                                    string[] vecListConfig = line.Split(' ');
                                    VHDDataConfig GetListConfig = new VHDDataConfig(vecListConfig[0], vecListConfig[1], vecListConfig[2], vecListConfig[3]);

                                    ListConfig.Add(GetListConfig);
                                }
                                catch { }
                            }
                            ListConnection.ItemsSource = ListConfig;
                        }
                    }
                    catch (Exception ex)
                    {
                        // Let the user know what went wrong.
                        MessageBox.Show(ex.Message, string.Empty, MessageBoxButton.OK, MessageBoxImage.Error);

                    }
                }
            }
            catch (Exception ex)
            { MessageBox.Show(ex.Message + "[" + (Const.FileConfig) + "]", string.Empty, MessageBoxButton.OK, MessageBoxImage.Error); }
        }

        private void AddConnectionLanguage()
        {

            ResManager = new System.Resources.ResourceManager("AzureDriverExplorer_Client.Properties.Resources", this.GetType().Assembly);



            Title_.Text = ResManager.GetString("UpdateVHD" + cons.Language).Trim();

            AccountNameTitle.Text = ResManager.GetString("AccountName" + cons.Language).Trim();
            AccountKeyTitle.Text = ResManager.GetString("AccountKey" + cons.Language).Trim();
            ContainerNameTitle.Text = ResManager.GetString("ContainerName" + cons.Language).Trim();

            txtFile.Content = ResManager.GetString("SelectFile" + cons.Language).Trim();
            Upload.Content = ResManager.GetString("Upload" + cons.Language).Trim();

            AccountName.Header = ResManager.GetString("AccountName" + cons.Language).Trim();            
            ContainerName.Header = ResManager.GetString("ContainerName" + cons.Language).Trim();
            VHDName.Header = ResManager.GetString("VHDName" + cons.Language).Trim();

            Add.Content = ResManager.GetString("Add" + cons.Language).Trim();
            CancelAdd.Content = ResManager.GetString("Cancel" + cons.Language).Trim();
            
            
        }

        private void txtFile_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
            ofd.Filter = "VHD Files(*.vhd)|*.vhd";
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtFile.Content = ofd.FileName;
                if (ofd.FileName.Length > 0)
                    Selected = true;
            }

        }

        private void Upload_Click(object sender, RoutedEventArgs e)
        {
            ReturnColor();

            if (!ValidaData())
                return;

            Enable(false);

            ProgressGrid.Visibility = Visibility.Visible;

            //Progress名を入れます
            thread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate()
            {
                Uploader();

                clearAfterUpdate();


            }));
            thread.Start();

            ReturnColor();

        }


        protected bool Uploader()
        {
            bool error = false;
            try
            {

                ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                {
                    BrushConverter bc = new BrushConverter();
                    Brush brush;
                    brush = (Brush)bc.ConvertFrom(Const.upColor(0));

                    ProgressUpload.Foreground = brush;
                    ProgressUpload.BorderBrush = brush;

                }));
                ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                {
                    txtProgress.Text = ResManager.GetString("Info_TryConecting" + cons.Language).Trim();
                }));

                // Use the storage emulator.

                CloudStorageAccount account = null;
                CloudBlobContainer container = null;

                string AccountName = string.Empty;
                string AccountKey = string.Empty;
                string ContainerName = string.Empty;
                string fFile = string.Empty;

                Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                {
                    AccountName = this.txtAccountName.Text;
                    AccountKey = this.txtAccountKey.Password;
                    ContainerName = this.txtContainerName.Text;
                    fFile = this.txtFile.Content.ToString();

                }));
                account = CloudStorageAccount.Parse("DefaultEndpointsProtocol=http;AccountName=" + AccountName + ";AccountKey=" + AccountKey);

                // Create the Blob service client.
                CloudBlobClient client = account.CreateCloudBlobClient();

                // Create the container for the drive if it does not already exist.

                container = new CloudBlobContainer(ContainerName, client);

                container.CreateIfNotExist();

                //container.Uri
                string blobUri = "http://" + container.Uri.Host + "/" + ContainerName + "/" + System.IO.Path.GetFileName(fFile);//txtvhdName.Text;

                // check args
                //********************************

                using (FileStream file = File.OpenRead(fFile))
                {
                    int pageSize = 1024 * 1024;
                    int numPages = (int)(file.Length / pageSize);
                    long blobSize = (file.Length / 512) * 512; // page size needs to be multiple of 512
                    if ((file.Length % 512) > 0)
                    {
                        // adjust to the next 512 bytes boundary
                        blobSize += 512;
                        //Output("Warning : file size adjusted to {0} (512 boundary)", blobSize);
                    }
                    //Trace("File size : {0:0,0}", file.Length);
                    //Trace("Page size : {0:0,0}", pageSize);
                    //Trace("Pages     : {0}", numPages);
                    //Trace("Remainder : {0:0,0}", blobSize - pageSize * numPages);
                    //Trace("");

                    //Trace("Create blob : {0}", blobUri);
                    CloudBlobClient blobStorage = account.CreateCloudBlobClient();
                    CloudPageBlob blob = blobStorage.GetPageBlobReference(blobUri);

                    blob.Properties.ContentType = "binary/octet-stream";
                    blob.Create(blobSize);

                    byte[] page = new byte[pageSize];
                    using (MemoryStream stmPage = new MemoryStream(page))
                    {
                        // process all pages until last
                        for (int i = 0; i < numPages; i++)
                        {
                            // status update
                            ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                           {
                               ProgressUpload.Value = ((i + 1) * 100 / numPages);
                               int value = (int)ProgressUpload.Value;


                               BrushConverter bc = new BrushConverter();
                               Brush brush;
                               brush = (Brush)bc.ConvertFrom(Const.upColor(value));

                               ProgressUpload.Foreground = brush;
                               ProgressUpload.BorderBrush = brush;

                           }));
                            ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                          {
                              txtProgress.Text = ProgressUpload.Value.ToString() + "%";
                          }));
                            //labInfo.Text = ("Uploading - " + (i + 1) + " / " + numPages.ToString());

                            // write page to storage
                            file.Read(page, 0, pageSize);
                            stmPage.Seek(0, SeekOrigin.Begin);
                            blob.WritePages(stmPage, i * pageSize);
                        }

                        // process last page
                        if (blobSize > numPages * pageSize)
                        {
                            int remain = (int)(blobSize - (numPages * pageSize));
                            page = new byte[remain];    // allocate a clean buffer, padding with zero
                            //Trace("Last page : {0:0,0}", remain);
                            //Trace("Padding   : {0:0,0}", file.Length % 512);

                            using (MemoryStream stmLast = new MemoryStream(page))
                            {
                                // write page to storage
                                file.Read(page, 0, remain);
                                stmLast.Seek(0, SeekOrigin.Begin);
                                blob.WritePages(stmLast, numPages * pageSize);
                            }
                        }

                     

                    }

                    ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        txtProgress.Text = ResManager.GetString("Completed" + cons.Language).Trim();
                    }));
                    // status update
                    MessageBox.Show(ResManager.GetString("Completed" + cons.Language).Trim(), string.Empty, MessageBoxButton.OK, MessageBoxImage.Information);

                    ProgressGrid.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                          {
                              ProgressGrid.Visibility = Visibility.Hidden;
                          }));

                }
            }
            catch (Exception ex)
            {

                if (!Cancel)
                {
                    ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        ProgressUpload.Value = 100;

                        BrushConverter bc = new BrushConverter();
                        Brush brush;
                        brush = (Brush)bc.ConvertFrom(Const.upColor(101));

                        ProgressUpload.Foreground = brush;
                        ProgressUpload.BorderBrush = brush;

                    }));

                    ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        txtProgress.Text = ResManager.GetString("Error" + cons.Language).Trim();
                    }));

                    MessageBox.Show(ResManager.GetString("Error" + cons.Language).Trim()+": " + ex.Message, string.Empty, MessageBoxButton.OK, MessageBoxImage.Error);

                    ProgressGrid.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        ProgressGrid.Visibility = Visibility.Hidden;
                    }));
                    error = true;
                }
                else
                {
                    ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                                           {
                                               ProgressUpload.Value = 100;

                                               BrushConverter bc = new BrushConverter();
                                               Brush brush;
                                               brush = (Brush)bc.ConvertFrom(Const.upColor(102));

                                               ProgressUpload.Foreground = brush;
                                               ProgressUpload.BorderBrush = brush;

                                           }));

                    ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        txtProgress.Text = ResManager.GetString("Canceled" + cons.Language).Trim();
                    }));

                    System.Threading.Thread.Sleep(2000);

                    ProgressGrid.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                    {
                        ProgressGrid.Visibility = Visibility.Hidden;
                    }));
                   
                    error = true;
                }
            }
            finally
            {
                EnableUpdate(true);
                Cancel = false;
            }

            return error;
        }


        /// <summary>
        /// Validate data Add
        /// </summary>
        /// <returns></returns>
        private bool ValidaData()
        {
            bool Result = true;
            this.txtAccountName.Text = this.txtAccountName.Text.Replace(" ", "");
            this.txtAccountKey.Password = this.txtAccountKey.Password.Replace(" ", "");
            this.txtContainerName.Text = this.txtContainerName.Text.Replace(" ", "");


            if (this.txtAccountName.Text.Equals(string.Empty))
            {
                Result = false;
                this.txtAccountName.BorderBrush = Brushes.Red;
            }

            if (this.txtAccountKey.Password.Equals(string.Empty))
            {
                Result = false;
                this.txtAccountKey.BorderBrush = Brushes.Red;
            }

            if (this.txtContainerName.Text.Equals(string.Empty))
            {
                Result = false;
                this.txtContainerName.BorderBrush = Brushes.Red;
            }

            if (!Selected)
            {
                Result = false;
                this.txtFile.Content = ResManager.GetString("Info_SelectArchivo2" + cons.Language).Trim();
                this.txtFile.BorderBrush = Brushes.Red;
            }
            return Result;

        }




        /// <summary>
        /// Clear the data
        /// </summary>
        private void clear()
        {

            this.txtAccountName.Text = "";
            this.txtAccountKey.Password = "";
            this.txtContainerName.Text = "";
            this.txtFile.Content = ResManager.GetString("SelectFile" + cons.Language).Trim(); 

        }

        /// <summary>
        /// Clear the data After update
        /// </summary>
        private void clearAfterUpdate()
        {
            this.txtAccountName.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
             {

                 this.txtAccountName.Text = "";
             }));
            this.txtAccountKey.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
            {
                this.txtAccountKey.Password = "";
            }));
            this.txtContainerName.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
           {
               this.txtContainerName.Text = "";
           }));
            this.txtFile.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
           {
               this.txtFile.Content = ResManager.GetString("SelectFile" + cons.Language).Trim(); 
           }));

            ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
            {
                txtProgress.Text = "";
            }));

            ProgressUpload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
               {
                   ProgressUpload.Value = 0;
               }));

        }


        /// <summary>
        /// return color
        /// </summary>
        /// <returns></returns>
        private void ReturnColor()
        {

            //Add
            this.txtAccountName.BorderBrush = Brushes.AliceBlue;
            this.txtAccountKey.BorderBrush = Brushes.AliceBlue;
            this.txtContainerName.BorderBrush = Brushes.AliceBlue;
            this.txtFile.BorderBrush = Brushes.AliceBlue;


        }

        /// <summary>
        /// Enable
        /// </summary>
        /// <param name="enable"></param>
        private void Enable(bool enable)
        {           
                this.txtAccountName.IsEnabled = enable;
                this.txtAccountKey.IsEnabled = enable;
                this.txtContainerName.IsEnabled = enable;
                this.txtFile.IsEnabled = enable;
                this.Upload.IsEnabled = enable;
                this.CloseWindows.IsEnabled = enable;
                this.AddDataFile.IsEnabled = enable; 
            
        }


        /// <summary>
        /// Enable in Under Prosess
        /// </summary>
        /// <param name="enable"></param>
        private void EnableUpdate(bool enable)
        {

          
                this.txtAccountName.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
             {
                 this.txtAccountName.IsEnabled = enable;
             }));
                this.txtAccountKey.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
             {
                 this.txtAccountKey.IsEnabled = enable;
             }));
                this.txtContainerName.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
             {
                 this.txtContainerName.IsEnabled = enable;
             }));
                this.txtFile.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
               {
                   this.txtFile.IsEnabled = enable;
               }));
                this.Upload.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
              {
                  this.Upload.IsEnabled = enable;
              }));
                this.CloseWindows.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                {
                    this.CloseWindows.IsEnabled = enable;
                }));
                this.AddDataFile.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(delegate()
                {
                    this.AddDataFile.IsEnabled = enable;
                }));
            

        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            Cancel = true;

            // Wait for 3sec
            System.Threading.Thread.Sleep(3000);

            // Stop Thread
            thread.Abort();

        }

        private void Close_popupVhdUpload_Click(object sender, RoutedEventArgs e)
        {
            this.Visibility = Visibility.Hidden;
        }

        private void popupGetDataFile_Click(object sender, RoutedEventArgs e)
        {
            popupGetDataFile.Visibility = Visibility.Visible;
        }

        private void Close_popupGetDataFile_Click(object sender, RoutedEventArgs e)
        {
            popupGetDataFile.Visibility = Visibility.Hidden;
        }

        private void Add_popupGetDataFile_Click(object sender, RoutedEventArgs e)
        {
            if (ListConnection.SelectedItem == null)
            {
                MessageBox.Show(ResManager.GetString("Info_Select_Data_List" + cons.Language).Trim(), string.Empty, MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            VHDDataConfig GetDataConfig = ListConnection.SelectedItem as VHDDataConfig;
            txtAccountName.Text = GetDataConfig.AccountName;
            txtAccountKey.Password = GetDataConfig.AccountKey;
            txtContainerName.Text = GetDataConfig.ContainerName;

            popupGetDataFile.Visibility = Visibility.Hidden;
        }
        
    }
}
